
#ifndef _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_
#define _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>

#define XP_UNIX
#define JS_THREADSAFE
#include <js/jsapi.h>
#include <js/jsxdrapi.h>
#include <js/jsdbgapi.h>

typedef struct {
	JSRuntime *jsr;
	size_t memory;
} ngx_http_javascript_main_conf_t;

typedef struct {
	size_t quota;
	ngx_str_t magic;
	ngx_str_t output;
	ngx_str_t basedir;
	ngx_str_t realdir;
	ngx_int_t timeout;
	ngx_flag_t enable;
	ngx_flag_t cache_xdr;
} ngx_http_javascript_loc_conf_t;

typedef struct {
	ngx_http_request_t *r;
	ngx_int_t timeout;
	ngx_int_t step;
	ngx_str_t path;
	size_t root;
} ngx_javascript_private_t;

extern ngx_module_t ngx_http_javascript_module;

void *ngx_http_javascript_create_main_conf(ngx_conf_t *cf);
char *ngx_http_javascript_init_main_conf(ngx_conf_t *cf, void *conf);
void *ngx_http_javascript_create_loc_conf(ngx_conf_t *cf);
char *ngx_http_javascript_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
char *ngx_http_javascript_init_post(ngx_conf_t *cf, void *cmd, void *conf);

ngx_int_t ngx_http_javascript_handler(ngx_http_request_t *r);
void ngx_http_javascript_handle_request(ngx_http_request_t *r);

JSBool ngx_javascript_error(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_throw(JSContext *jcx, const char *message);
void ngx_javascript_global_error(JSContext *jcx, const char *message, JSErrorReport *report);
JSBool ngx_javascript_outofmemory(JSContext *jcx);
JSBool ngx_javascript_timeout(JSContext *jcx);

JSBool ngx_javascript_global_load(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_alert(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_print(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_file_string(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_line_string(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);

JSBool ngx_javascript_read_server(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);
JSBool ngx_javascript_read_headers(JSContext *jcx, JSObject *obj, JSObject *global_server, ngx_http_request_t *r);
JSBool ngx_javascript_read_request(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, int arg);
JSBool ngx_javascript_write_headers(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);

JSBool ngx_javascript_register_variable(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, u_char *var, size_t var_len, u_char *val, size_t val_len);
JSBool ngx_javascript_register_variable_r(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, u_char *var, size_t var_len, u_char *val, size_t val_len);

JSBool ngx_javascript_execute_script(JSContext *jcx, JSObject *obj, const char *fileName, jsval *rval);
JSBool ngx_javascript_check_basedir(JSContext *jcx, const char *filename);
JSBool ngx_javascript_check_basedir_realpath(JSContext *jcx, const char *filename);

JSBool ngx_javascript_file_line(JSContext *jcx, const char **file, int *line);

u_char *ngx_javascript_string_token(u_char *s, const u_char *delim, u_char ** last);
u_char *ngx_pstrdup0(ngx_pool_t *pool, ngx_str_t *src);

static JSClass ngx_javascript_global_class = {
	"Global",
	JSCLASS_GLOBAL_FLAGS,
	JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
	JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
	JSCLASS_NO_OPTIONAL_MEMBERS
};

static JSClass ngx_javascript_standard_class = {
	"Standard",
	0,
	JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
	JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
	JSCLASS_NO_OPTIONAL_MEMBERS
};

static JSClass ngx_javascript_error_class = {
	"Error",
	0,
	JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
	JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
	JSCLASS_NO_OPTIONAL_MEMBERS
};

static JSPropertySpec ngx_javascript_error_props[] = {
	{ "message", 0, 0, 0, 0 },
	{ "file", 0, 0, 0, 0 },
	{ "line", 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0 }
};

#define NGX_JAVASCRIPT_PRIVATE_ERROR "context private error"

#define NGX_JAVASCRIPT_PARSE_POST 0
#define NGX_JAVASCRIPT_PARSE_GET 1
#define NGX_JAVASCRIPT_PARSE_COOKIE 2
#define NGX_JAVASCRIPT_PARSE_STRING 3
#define NGX_JAVASCRIPT_PARSE_ENV 4
#define NGX_JAVASCRIPT_PARSE_SERVER 5
#define NGX_JAVASCRIPT_PARSE_SESSION 6

#ifdef NGX_JAVASCRIPT_HAVE_SQLITE
extern JSBool ngx_javascript_init_sqlite(JSContext *jcx, JSObject *global);
#endif /* NGX_JAVASCRIPT_HAVE_SQLITE */

#endif /* _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_ */
